﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using BankCreditPortfolio.Attributes;
using BankCreditPortfolio.Models.BankModels;
using BankCreditPortfolio.DAL.Entities;
using BankCreditPortfolio.DAL.Services;
using BankCreditPortfolio.Models.ClientCabinetModels;
using MvcContrib.Pagination;
using BankCreditPortfolio.Core.Helpers;
using OrderInfoModel = BankCreditPortfolio.Models.BankModels.OrderInfoModel;

namespace BankCreditPortfolio.Controllers
{
    [IsBanker]
    public class BankController : BaseController
    {
        //
        // GET: /Bank/Orders
        public ActionResult Orders(int? page)
        {
            var role = (new BankerService()).GetByEmail(User.Identity.Name).Account.Role.Title;
            var orderService = new OrderInfoService();
            IQueryable<OrderInfo> orders;
            switch (role)
            {
                case "OperationsAnalyst":
                    orders = orderService.GetAllByStatus("Received for review");
                    break;
                case "SafetyOfficer":
                    orders = orderService.GetAllByStatus("Correctness approved");
                    break;
                case "CustomerEngineer":
                    orders = orderService.GetAllByStatus("Safety approved");
                    break;
                case "CreditCommitteeMember":
                    orders = orderService.GetAllByStatus("Validity approved");
                    break;
                default:
                    orders = null;
                    break;
            }
            IEnumerable<OrderInfo> orderItems = orders != null ? orders.ToList() : new List<OrderInfo>();
            return View(orderItems.AsPagination(page ?? 1, 10));
        }

        //
        // GET: /Bank/OrderInfo

        public ActionResult OrderInfo(int orderId)
        {
            return View(GetFilledOrderInfoModel(orderId));
        }

        private OrderInfoModel GetFilledOrderInfoModel(int orderId)
        {
            var model = new OrderInfoModel();
            var order = (new OrderInfoService()).Find(orderId);
            model.Currency = order.Currency.Title;
            if (order.Guarantors.Count > 0)
            {
                var guarantor = order.Guarantors.First();
                model.GuarantorId = guarantor.GuarantorId;
            }
            model.TariffTitle = order.Tariff.Title;
            model.TariffId = order.Tariff.TariffId;
            model.Amount = order.Amount;
            model.Status = order.OrderStatus.Status;
            model.ClientId = order.Client.ClientId;
            model.OrderId = orderId;
            model.GuarantorExists = order.Guarantors.Count > 0;
            model.DocPath = order.Documents;
            model.DocumentsRequired = (new TariffService()).Find(order.Tariff.TariffId).Documents.Count > 0;
            return model;
        }

        [HttpPost]
        public ActionResult OrderInfo(OrderInfoModel model, string submitButton)
        {
            switch (submitButton)
            {
                case "Approve":
                    return ApproveOrder(model.OrderId, model.Comment);
                case "Reject":
                    if (string.IsNullOrEmpty(model.Comment))
                    {
                        ModelState.AddModelError("", "Comment should be filled in rejection case.");
                        return View(GetFilledOrderInfoModel(model.OrderId));
                    }
                    return RejectOrder(model.OrderId, model.Comment);
            }
            return View(model);
        }

        //
        // GET: /Bank/ClientInfo

        public ActionResult ClientInfo(int clientId)
        {
            var model = new ClientInfoModel();
            var client = (new ClientService()).Find(clientId);
            model.Address = client.Profile.Adress;
            model.Email = client.Account.Email;
            model.FirstName = client.Profile.FirstName;
            model.LastName = client.Profile.LastName;
            model.MiddleName = client.Profile.MiddleName;
            model.PassportDate = client.Profile.PassportDate.ToShortDateString();
            model.PassportIssuingAuthority = client.Profile.PassportIssuingAuthority;
            model.PersonalId = client.Profile.PersonalId;
            model.Phone = client.Profile.Phone;
            model.Workplace = client.Profile.Work;
            return View(model);
        }

        //
        // GET: /Bank/GuarantorInfo

        public ActionResult GuarantorInfo(int guarantorId)
        {
            var model = new GuarantorInfoModel();
            var guarantor = (new GuarantorService()).Find(guarantorId);

            model.Gains = guarantor.Gains;
            model.GainsCurrency = guarantor.GainsCurrency.Title;
            model.Address = guarantor.Profile.Adress;
            model.FirstName = guarantor.Profile.FirstName;
            model.LastName = guarantor.Profile.LastName;
            model.MiddleName = guarantor.Profile.MiddleName;
            model.PassportDate = guarantor.Profile.PassportDate.ToShortDateString();
            model.PassportIssuingAuthority = guarantor.Profile.PassportIssuingAuthority;
            model.PersonalId = guarantor.Profile.PersonalId;
            model.Phone = guarantor.Profile.Phone;
            model.Workplace = guarantor.Profile.Work;
            return View(model);
        }

        //
        // GET: /Bank/CreateAgreement

        public ActionResult CreateAgreement(int orderId)
        {
            var depositService = new DepositService();
            var orderInfoService = new OrderInfoService();
            var order = orderInfoService.Find(orderId);
            var bank = depositService.GetBankDeposit(order.Currency.Title);
            if (bank.Amount < order.Amount)
            {
                ViewBag.Message = "The agreement creation failed. There is no enough money in bank";
                order.OrderStatus = (new OrderStatusService()).GetByTitle("Rejected");
                orderInfoService.Update(ref order);
                return View();
            }
            bank.Amount -= order.Amount;
            depositService.Save(ref bank);

            var agreement = new Agreement {Order = order};
            var deposit = new Deposit
                              {
                                  Amount = order.Amount,
                                  Currency = order.Currency,
                                  DepositType = (new DepositTypeService()).GetByTitle("Client"),
                                  Account = order.Client.Account
                              };
            agreement.Banker = (new BankerService()).GetByEmail(User.Identity.Name);
            var credit = new Credit
                             {
                                 DeliveryDate = DateTime.Now,
                                 Deposit = deposit
                             };
            agreement.Credit = credit;
            try
            {
                depositService.Save(ref deposit);
                (new CreditService()).Save(ref credit);
                var agreementService = new AgreementService();
                agreementService.Save(ref agreement);
                ViewBag.Message = "The agreement has been created successfully.";
                ViewBag.AgreementId = agreementService.GetByOrderId(order.OrderId).AgreementId;
            }
            catch (Exception)
            {
                ViewBag.Message = "The agreement creation failed.";
            }
            return View();
        }

        public ActionResult ApproveOrder(int orderId, string comment)
        {
            var orderInfoService = new OrderInfoService();
            var orderStatusService = new OrderStatusService();
            var order = orderInfoService.Find(orderId);
            UpdateOrderHistory(orderId, comment);
            var role = (new BankerService()).GetByEmail(User.Identity.Name).Account.Role.Title;
            switch (role)
            {
                case "OperationsAnalyst":
                    order.OrderStatus = orderStatusService.GetByTitle("Correctness approved");
                    break;
                case "SafetyOfficer":
                    order.OrderStatus = orderStatusService.GetByTitle("Safety approved");
                    break;
                case "CustomerEngineer":
                    order.OrderStatus = orderStatusService.GetByTitle("Validity approved");
                    break;
                case "CreditCommitteeMember":
                    order.OrderStatus = orderStatusService.GetByTitle("Approved");
                    break;
            }
            orderInfoService.Update(ref order);
            return order.OrderStatus.Status == "Approved"
                       ? RedirectToAction("CreateAgreement", new {orderId})
                       : RedirectToAction("ApproveSuccess");
        }

        public ActionResult ApproveSuccess()
        {
            return View();
        }

        public ActionResult RejectOrder(int orderId, string comment)
        {
            var orderInfoService = new OrderInfoService();
            var orderStatusService = new OrderStatusService();
            var order = orderInfoService.Find(orderId);
            UpdateOrderHistory(orderId, comment);
            order.OrderStatus = orderStatusService.GetByTitle("Rejected");
            orderInfoService.Update(ref order);
            return RedirectToAction("RejectSuccess");
        }

        private void UpdateOrderHistory(int orderId, string comment)
        {
            var orderHistory = OrderHistoryHelper.GetOrderHistory(orderId);

            var role = (new BankerService()).GetByEmail(User.Identity.Name).Account.Role.Title;
            switch (role)
            {
                case "OperationsAnalyst":
                    orderHistory.OperationsAnalyst = (new BankerService()).GetByEmail(User.Identity.Name);
                    orderHistory.DateOperationsAnalyst = DateTime.Now;
                    orderHistory.CommentsOperationsAnalyst = comment;
                    break;
                case "SafetyOfficer":
                    orderHistory.SafetyOfficer = (new BankerService()).GetByEmail(User.Identity.Name);
                    orderHistory.DateSafetyOfficer = DateTime.Now;
                    orderHistory.CommentsSafetyOfficer = comment;
                    break;
                case "CustomerEngineer":
                    orderHistory.CustomerEngineer = (new BankerService()).GetByEmail(User.Identity.Name);
                    orderHistory.DateCustomerEngineer = DateTime.Now;
                    orderHistory.CommentsCustomerEngineer = comment;
                    break;
                case "CreditCommitteeMember":
                    orderHistory.CreditCommittieMember = (new BankerService()).GetByEmail(User.Identity.Name);
                    orderHistory.DateCreditCommittieMember = DateTime.Now;
                    orderHistory.CommentsCreditCommittieMember = comment;
                    break;
            }
            orderHistory.OrderInfo = (new OrderInfoService()).GetAll().Where(x => x.OrderId == orderId).First();

            (new OrderHistoryService()).Save(ref orderHistory);
        }

        public ActionResult RejectSuccess()
        {
            return View();
        }

        //
        // GET: /Bank/Payments
        [IsCreditCommitteeMember]
        public ActionResult Payments(int? page)
        {
            var payments = (new PaymentService()).GetAll();
            IEnumerable<Payment> paymentItems = payments != null ? payments.ToList() : new List<Payment>();
            return View(paymentItems.AsPagination(page ?? 1, 10));
        }

        //
        // GET: /Bank/BankDeposits
        [IsCreditCommitteeMember]
        public ActionResult BankDeposits(int? page)
        {
            var deposits = (new DepositService()).GetBankDeposits();
            IEnumerable<Deposit> depositItems = deposits != null ? deposits.ToList() : new List<Deposit>();
            return View(depositItems.AsPagination(page ?? 1, 10));
        }

        //
        // GET: /Bank/Orders
        public ActionResult OrdersArchive(int? page)
        { 
            var orderService = new OrderInfoService();
            var orders = orderService.GetArchiveOrders();
            IEnumerable<OrderInfo> orderItems = orders != null ? orders.ToList() : new List<OrderInfo>();
            return View(orderItems.AsPagination(page ?? 1, 10));
        }

        //
        // GET: /Bank/Credits

        public ActionResult Credits(int? page)
        {
            var credits = (new AgreementService()).GetActive();
            IEnumerable<Agreement> creditItems = credits != null ? credits.ToList() : new List<Agreement>();
            return View(creditItems.AsPagination(page ?? 1, 10));
        }

        public ActionResult ShowAgreement(int agreementId)
        {
            var agreementService = new AgreementService();
            var agreement = agreementService.Find(agreementId);
            var model = new CreditAgreementModel().MapFrom(agreement);
            return View("CreditAgreement", model);
        }

        public ActionResult OrderHistory(int orderId, bool inProgressOrder = true)
        {
            var model = OrderHistoryHelper.GetOrderHistory(inProgressOrder, User.Identity.Name, orderId);
            return View(model);
        }
    }
}
